package org.anupta.game.entity.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.anupta.game.entity.entities.Entity;

public abstract class DAO<T extends Entity> {
    private static final Map<Class<? extends Entity>, DAO<? extends Entity>> dao = new HashMap<Class<? extends Entity>, DAO<? extends Entity>>();

    private Map<Integer, T> toUpdate = new HashMap<Integer, T>();
    private Map<Integer, T> toCreate = new HashMap<Integer, T>();
    private Map<Integer, T> toDelete = new HashMap<Integer, T>();

	@SuppressWarnings("unchecked")
	public static <T extends Entity> DAO<T> getDao(Class<T> clas) {
        return (DAO<T>) dao.get(clas);
    }
    public static List<DAO<? extends Entity>> getDao() {
        return new ArrayList<DAO<? extends Entity>>(dao.values());
    }

    public static <T extends Entity> void setDao(Class<T> clas, DAO<T> t) {
        dao.put(clas, t);
    }

    public void create(T object) {
    	synchronized(this){
    		if (!getDelete().containsValue(object) && !getCreate().containsValue(object)) {
    			getCreate().put(object.getGuid(), object);
    		}
    	}
    }

    public void update(T object) {
    	synchronized(this){
    		if (!getDelete().containsValue(object) && !getUpdate().containsValue(object)) {
    			getUpdate().put(object.getGuid(), object);
    		}
    	}
    }

    public void delete(T object) {
    	synchronized(this){
    		if (!getDelete().containsValue(object)) {
    			getDelete().put(object.getGuid(), object);
    			if (getCreate().containsValue(object)) {
    				getCreate().remove(object.getGuid());
    			}
    			if (getUpdate().containsValue(object)) {
    				getUpdate().remove(object.getGuid());
    			}
    		}
    	}
    }
    
    public synchronized Map<Integer, T> getUpdate(){
    	return toUpdate;
    }
    public synchronized Map<Integer, T> getCreate(){
    	return toCreate;
    }
    public synchronized Map<Integer, T> getDelete(){
    	return toDelete;
    }

    public abstract T find(int id);
    public abstract T find(String name);
    public abstract List<T> findAll();
    public abstract void commit();
}
